package com.star.star.service.impl;

import cn.hutool.core.lang.Assert;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.star.common.enums.AuditStatus;
import com.star.mentor.service.EvaluationItemService;
import com.star.mentor.service.MentorEvaluationService;
import com.star.star.vo.StarDetailWxmentorVO;
import com.star.news.service.NewsService;
import com.star.star.dto.*;
import com.star.star.entity.Star;
import com.star.star.entity.StarArt;
import com.star.star.mapper.StarMapper;
import com.star.star.service.StarArtService;
import com.star.star.service.StarChatService;
import com.star.star.service.StarPhotoService;
import com.star.star.service.StarService;
import com.star.star.struct.StarStruct;
import com.star.star.vo.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 艺人 服务实现类
 *
 * @author yangzj
 */
@Service
public class StarServiceImpl extends ServiceImpl<StarMapper, Star> implements StarService {

    @Autowired
    private StarArtService starArtService;
    @Autowired
    private StarPhotoService starPhotoService;
    @Autowired
    private StarChatService starChatService;
    @Autowired
    private NewsService newsService;
    @Autowired
    private EvaluationItemService evaluationItemService;
    @Autowired
    private MentorEvaluationService mentorEvaluationService;

    @Override
    public void updateSigning(Long id, boolean isSigning) {
        this.updateById(new Star().setId(id).setIsSigning(isSigning).setSigningTime(LocalDateTime.now()));
    }

    @Override
    public void updateEnabled(Long id, boolean enabled) {
        this.updateById(new Star().setId(id).setEnabled(enabled));
    }

    @Override
    public void updateScore(Long id, BigDecimal score) {
        this.updateById(new Star().setId(id).setScore(score));
    }

    @Override
    public IPage<StarPageVO> page(StarPageDTO dto) {
        return baseMapper.page(dto);
    }

    @Override
    public StarDetailVO getDetail(Long id) {
        StarDetailVO detail = Assert.notNull(baseMapper.getDetail(id), "艺人不存在");
        detail.setNewsList(newsService.listLatestByStarId(id, 3))
                .setPhotos(starPhotoService.listByStarId(id, null, null, null))
                .setArts(starArtService.listByStarId(id, null, null, null));
        return detail;
    }

    @Override
    public IPage<StarFileAuditPageVO> auditPage(StarFileAuditPageDTO dto) {
        return baseMapper.auditPage(dto);
    }

    @Override
    public StarFileAuditDetailVO getAuditDetail(Long id) {
        StarFileAuditDetailVO detail = Assert.notNull(baseMapper.getAuditDetail(id), "艺人不存在");
        detail.setPhotos(starPhotoService.listByStarId(id, null, AuditStatus.WAIT.getCode(), null))
                .setArts(starArtService.listByStarId(id, null, AuditStatus.WAIT.getCode(), null));
        return detail;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void auditFile(StarFileAuditDTO dto) {
        starPhotoService.auditBatch(dto.getPhotos());
        starArtService.auditBatch(dto.getArts(), dto.getId());
    }

    @Override
    public StarAnalysisVO getAnalysis(Long id) {
        return new StarAnalysisVO().setCities(baseMapper.listCityAnalysis(id))
                .setGenders(baseMapper.listGenderAnalysis(id))
                .setArts(starArtService.listByStarId(id, null, null, null));
    }

    @Override
    public boolean isSigning(Long id) {
        Star star = Assert.notNull(this.getById(id), "艺人不存在");
        return star.getIsSigning();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Long saveBaseInfoWxuser(StarSaveWxuserDTO dto, Long userId) {
        Star star = StarStruct.INSTANCE.to(dto).setCollectCount(0).setSupportCount(0).setUserId(userId).setIsSigning(false).setEnabled(true);
        this.save(star);
        return star.getId();
    }

    @Override
    public void updateBaseInfoWxuser(StarUpdateWxuserDTO dto, Long userId) {
        this.check(dto.getId(), userId);
        Star star = StarStruct.INSTANCE.to(dto);
        this.update(star, Wrappers.<Star>lambdaUpdate().eq(Star::getId, dto.getId()).set(Star::getRealName, dto.getRealName()).set(Star::getPhone, dto.getPhone()).set(Star::getBirthDate, dto.getBirthDate()).set(Star::getHeight, dto.getHeight()).set(Star::getWeight, dto.getWeight()).set(Star::getBloodType, dto.getBloodType()).set(Star::getConstellation, dto.getConstellation()).set(Star::getEmail, dto.getEmail()).set(Star::getProvince, dto.getProvince()).set(Star::getCity, dto.getCity()));
    }

    @Override
    public StarBaseInfoWxuserVO getBaseInfoWxuser(Long id, Long userId) {
        return baseMapper.getBaseInfoWxuser(id, userId);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void updateIntroductionWxuser(StarIntroductionUpdateWxuserDTO dto, Long userId) {
        this.check(dto.getId(), userId);
        this.update(Wrappers.<Star>lambdaUpdate().eq(Star::getId, dto.getId()).set(Star::getIntroduction, dto.getIntroduction()));
    }

    @Override
    public String getIntroductionWxuser(Long id, Long userId) {
        return baseMapper.getIntroductionWxuser(id, userId);
    }

    @Override
    public IPage<StarPageWxuserVO> pageWxuser(StarPageWxuserDTO dto) {
        IPage<StarPageWxuserVO> page = baseMapper.pageWxuser(dto);
        List<StarPageWxuserVO> records = page.getRecords();
        if (records.isEmpty()) {
            return page;
        }
        // 取代表作品
        List<Long> starIds = records.stream().map(StarPageWxuserVO::getId).collect(Collectors.toList());
        Map<Long, List<StarArt>> artMap = starArtService.listPlayTop(starIds).stream().collect(Collectors.groupingBy(StarArt::getStarId, Collectors.toList()));
        records.forEach(c -> {
            List<StarArt> starArts = artMap.get(c.getId());
            if (starArts != null) {
                c.setTopArts(starArts.stream().map(StarArt::getName).collect(Collectors.toList()));
            }
        });
        return page;
    }

    @Override
    public StarDetailWxuserVO getDetailWxuser(Long id, Long userId) {
        StarDetailWxuserVO detail = Assert.notNull(baseMapper.getDetailWxuser(id, userId), "艺人不存在");
        detail.setUnreadCount(starChatService.getFansUnread(detail.getId(), userId))
                .setNews(newsService.getLatestByStarId(id))
                .setPhotos(starPhotoService.listByStarId(id, true, null, null))
                .setArts(starArtService.listByStarId(id, true, null, null));
        return detail;
    }

    @Override
    public List<StarListVO> listWebTop(int limit) {
        List<StarListVO> list = baseMapper.listWebTop(limit);
        if (list.isEmpty()) {
            return list;
        }
        // 取代表作品
        List<Long> starIds = list.stream().map(StarListVO::getId).collect(Collectors.toList());
        Map<Long, List<StarArt>> artMap = starArtService.listPlayTop(starIds).stream().collect(Collectors.groupingBy(StarArt::getStarId, Collectors.toList()));
        list.forEach(c -> {
            List<StarArt> starArts = artMap.get(c.getId());
            if (starArts != null) {
                c.setTopArts(starArts.stream().map(StarArt::getName).collect(Collectors.toList()));
            }
        });
        return list;
    }

    @Override
    public IPage<StarPageWebVO> pageWeb(StarPageWebDTO dto) {
        return baseMapper.pageWeb(dto);
    }

    @Override
    public StarDetailWebVO getDetailWeb(Long id) {
        StarDetailWebVO detail = Assert.notNull(baseMapper.getDetailWeb(id), "艺人不存在");
        detail.setNews(newsService.getLatestByStarId(id))
                .setPhotos(starPhotoService.listByStarId(id, true, AuditStatus.OK.getCode(), null))
                .setArts(starArtService.listByStarId(id, true, null, null));
        return detail;
    }

    @Override
    public StarDetailWxmentorVO getDetailWxmentor(Long id, Long userId) {
        StarDetailWxmentorVO detail = Assert.notNull(baseMapper.getDetailWxmentor(id, userId), "艺人不存在");
        detail.setPhotos(starPhotoService.listByStarId(id, null, AuditStatus.OK.getCode(), null))
                .setArts(starArtService.listByStarId(id, null, AuditStatus.OK.getCode(), null))
                .setItems(evaluationItemService.listEvaluation(detail.getEvaluationId(), detail.getMentorEvaluationId()));
        // 更新已读
        mentorEvaluationService.updateRead(id, userId);
        return detail;
    }

    /**
     * 检查
     *
     * @param id     ID
     * @param userId 用户ID
     */
    public void check(Long id, Long userId) {
        Assert.isTrue(this.exists(id, userId), "艺人不存在");
    }

    @Override
    public boolean exists(Long id, Long userId) {
        return this.lambdaQuery().eq(Star::getId, id).eq(Star::getUserId, userId).exists();
    }

    @Override
    public void incrementCollectCount(Long id, boolean increment) {
        Star star = Assert.notNull(this.getById(id), "艺人不存在");
        int count = increment ? star.getCollectCount() + 1 : star.getCollectCount() - 1;
        this.updateById(new Star().setId(id).setCollectCount(count));
    }

    @Override
    public void incrementSupportCount(Long id, boolean increment) {
        Star star = Assert.notNull(this.getById(id), "艺人不存在");
        int count = increment ? star.getSupportCount() + 1 : star.getSupportCount() - 1;
        this.updateById(new Star().setId(id).setSupportCount(count));
    }

    @Override
    public Star getByUserId(Long userId) {
        return this.getOne(Wrappers.<Star>lambdaQuery().eq(Star::getUserId, userId));
    }
}
